package concurrent.queue.blockqueue;

import org.junit.Test;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

/**
 * 阻塞队列
 *
 * @author LoneRanger
 */
public class ArrayBlockQueueTest {

    /**
     * 如果可以在不违反容量限制的情况下立即将指定的元素插入此队列，则在成功时返回 {@code true}，如果当前没有可用空间则抛出 {@code IllegalStateException}。
     * 使用容量受限队列时，通常最好使用 {@link #offer(Object) offer}。
     */
    @Test
    public void testAdd() {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        /**
         * 插入接口add() 返回boolean值
         */
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));

        try {
            /**
             * add() 方法在queue满了的时候会报 queue full的错误
             */
            System.out.println(blockingQueue.add("X"));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * 检索并删除此队列的头部。 此方法与 {@link #poll() poll()} 的不同之处仅在于，如果此队列为空，则会引发异常。
     */
    @Test
    public void testRemove() {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(1);
        blockingQueue.add("c");

        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
    }

    /**
     * 从此队列中移除指定元素的单个实例，
     * 如果它存在。 更正式地说，删除一个元素 {@code e}，例如
     * {@code o.equals(e)}，如果这个队列包含一个或多个这样的
     * 元素。
     * 如果此队列包含指定的元素，则返回 {@code true}
     * （或等效地，如果此队列因调用而更改）。
     */
    @Test
    public void testRemove2() {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(1);
        blockingQueue.add("c");

        System.out.println(blockingQueue.remove("c"));
        System.out.println(blockingQueue.remove("c"));

    }

    /**
     * element()
     * 检索但不删除此队列的头部。 这种方法与 {@link #peek peek} 的不同之处仅在于，如果这个队列是空的，它抛出异常。
     * <p>
     * 仅仅拿出头部的元素，并返回，不会删除元素。如果队列为空，则抛出异常
     */
    @Test
    public void testElement() {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        System.out.println(blockingQueue.element());
    }

    /**
     * 如果可以在不违反容量限制的情况下立即将指定元素插入此队列，
     * 则在成功时返回 {@code true}，如果当前没有可用空间则返回 {@code false}。
     * 当使用容量受限的队列时，这种方法通常比 {@link #add} 更可取，后者只能通过抛出异常来插入元素失败。
     */
    @Test
    public void testOffer() {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        System.out.println(blockingQueue.offer("d"));
    }

    /**
     * 检索并移除此队列的头部，如果此队列为空，则返回 {@code null}。
     */
    @Test
    public void testPoll() {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(1);
        blockingQueue.offer("a");

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());


    }

    /**
     * 检索并移除此队列的头部，如果此队列为空，则返回 {@code null}。
     */
    @Test
    public void testPeek() {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(1);
        blockingQueue.offer("a");
        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());

    }

    /**
     * 检索并移除此队列的头部，如果此队列为空，则返回 {@code null}。
     */
    @Test
    public void testPut() throws InterruptedException {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(1);
        blockingQueue.put("a");
        blockingQueue.put("b");
    }

    /**
     * 检索并删除此队列的头部，必要时等待元素变为可用。
     */
    @Test
    public void testTake() throws InterruptedException {
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(1);
        blockingQueue.add("a");

        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());

    }
}
